﻿
/********************************************************************************
** Copyright(c) 2015 USTC & MSRA All Rights Reserved.
** auth： Zhaofan Qiu
** mail： zhaofanqiu@gmail.com
** date： 2015/12/13
** desc： Pooling3D layer
*********************************************************************************/

#ifndef CAFFE_POOLING3D_LAYER_HPP_
#define CAFFE_POOLING3D_LAYER_HPP_

#include <string>
#include <utility>
#include <vector>
#include "float.h"
#include "leveldb/db.h"
#include "boost/scoped_ptr.hpp"

#include "caffe/blob.hpp"
#include "caffe/common.hpp"
#include "caffe/layer.hpp"
#include "caffe/proto/caffe.pb.h"
#include "caffe/net.hpp"

#include "caffe/layers/video_common.hpp"

namespace caffe {
	/**
	* @brief Pools the input video by taking the max, average, etc. within regions.
	*
	* TODO(dox): thorough documentation for Forward, Backward, and proto params.
	*/
	template <typename Dtype>
	class Pooling3DLayer : public Layer<Dtype> {
	public:
		explicit Pooling3DLayer(const LayerParameter& param)
			: Layer<Dtype>(param) {}
		virtual void LayerSetUp(const vector<Blob<Dtype>*>& bottom,
			const vector<Blob<Dtype>*>& top);
		virtual void Reshape(const vector<Blob<Dtype>*>& bottom,
			const vector<Blob<Dtype>*>& top);

		virtual inline const char* type() const { return "Pooling3D"; }
		virtual inline int ExactNumBottomBlobs() const { return 1; }
		virtual inline int MinTopBlobs() const { return 1; }
		// MAX POOL layers can output an extra top blob for the mask;
		// others can only output the pooled inputs.
		virtual inline int MaxTopBlobs() const {
			return (this->layer_param_.pooling_param().pool() ==
				PoolingParameter_PoolMethod_MAX) ? 2 : 1;
		}

	protected:
		virtual void Forward_cpu(const vector<Blob<Dtype>*>& bottom,
			const vector<Blob<Dtype>*>& top);
		virtual void Forward_gpu(const vector<Blob<Dtype>*>& bottom,
			const vector<Blob<Dtype>*>& top);
		virtual void Backward_cpu(const vector<Blob<Dtype>*>& top,
			const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);
		virtual void Backward_gpu(const vector<Blob<Dtype>*>& top,
			const vector<bool>& propagate_down, const vector<Blob<Dtype>*>& bottom);

		int kernel_l_, kernel_h_, kernel_w_;
		int stride_l_, stride_h_, stride_w_;
		int pad_l_, pad_h_, pad_w_;
		int channels_;
		int length_, height_, width_;
		int pooled_length_, pooled_height_, pooled_width_;
		bool global_pooling_;
		Blob<Dtype> rand_idx_;
		Blob<int> max_idx_;
	};
}  // namespace caffe

#endif  // CAFFE_POOLING3D_LAYER_HPP_
